package com.mjk.common.web.getway.utils;


import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.tools.xml.XmlUtils;
import com.mjk.common.tools.lambada.LambdaReflectionUtil;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.StrUtils;
import com.mjk.common.web.getway.constns.GetwayConsts;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.HandlerMapping;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* 解析request 返回参数得键值对 包含GET/POST(StringEntry,NameValueEntry) 
* 同时包含JSON 键值对 XML 三种模式得解析
* @author mjk  
* @date 2019年3月11日
 */
public class RequstParaseUtils {
		
	/**
     * 判断是否是ajax请求
     */
    public static boolean isAjax(HttpServletRequest httpRequest) {
        return (httpRequest.getHeader("X-Requested-With") != null
                && "XMLHttpRequest"
                .equals(httpRequest.getHeader("X-Requested-With")));
    }
	/**
	 * 获取http请求头
     */
	public static Map<String, String> getHeaderFromRequest(
			HttpServletRequest request) {
		Map<String, String> map = new HashMap<>();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String key = headerNames.nextElement();
			String value = request.getHeader(key);
			map.put(key, value);
		}
		return map;
	}
	
	/**
	 * 把HTTP请求中的参数转为Map
     */
	public static Map<String, Object> getMapFromRequest(HttpServletRequest request) {	
			StringBuilder jb = new StringBuilder();
			String line;
			Map<String, Object> map = new HashMap<>();
			try {				
				BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
				while ((line = reader.readLine()) != null)
					jb.append(line);
				
				String sb = jb.toString();
				//规避request body中的 inputStream被取过一次之后，第二次取为空的问题
				if(ObjectUtils.isEmpty(sb)){
						Object o = LambdaReflectionUtil.invoke(request, "getBody", null);
						if(o!=null){
							sb = o.toString().replace("\n", "");
						}
				}
				Enumeration<String> paramNames = request.getParameterNames();
				while (paramNames.hasMoreElements()) {
					String paramName = paramNames.nextElement();
					if (GsonUtils.isJson(paramName))
						map.putAll(GsonUtils.json2Map(paramName));
					else if (ObjectUtils.isNotEmpty(paramName)) {
						map.put(paramName, request.getParameter(paramName));
					} 
				}				
				if(ObjectUtils.isNotEmpty(sb)){
					if (GsonUtils.isJson(sb)) {
						map.putAll(GsonUtils.gson2Map(sb));						
					}else if (XmlUtils.isXML(sb)) {
						//此处不支持xml 中的list
                        map.putAll(XmlUtils.xmlToMap(sb));
					}else if (sb.contains("&")) {
						sb = URLDecoder.decode(sb, StandardCharsets.UTF_8);
						map.putAll(postDataToMap(sb));
					}//规避aa=b没有匹配的问题
					else if(Pattern.matches(".*=.*", sb)){
						map.put(sb.substring(0, sb.indexOf("=")), sb.substring(sb.indexOf("=") + 1));
					}
				}
				if(ObjectUtils.isNotEmpty(sb))
					map.put(GetwayConsts.PARAMS_BODY	, sb);
			} catch (Exception e) {
				BizLogger.error(e);
			}
			return map;
	}
	
	/**
	 * 获取restful中的参数值
     */
	@SuppressWarnings("unchecked")
	public static Map<String,Object> getRestfulParams(HttpServletRequest request){
		NativeWebRequest webRequest = new ServletWebRequest(request);
		//获取restful url中的参数值
        return (Map<String, Object>) webRequest
				.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE,RequestAttributes.SCOPE_REQUEST);
	}

	public static Map<String, String> postDataToMap(String date) {
		Map<String, String> map = new HashMap<>();
		if (date.contains("&")) {
			String[] params = date.split("&");
			for (String param : params) {
				if (param.contains("=")) {
					if (StrUtils.searchStrNumber(param, "=") > 1) {
						map.put(param.substring(0, param.indexOf("=")), param.substring(param.indexOf("=") + 1));
					} else {
						String[] p = param.split("=");
						if (p.length > 1)
							map.put(p[0], p[1]);
						else {
							map.put(p[0], "");
						}
					}
				}
			}
		}
		return map;
	}
}